package com.lt.lumentracks.controller.websocket;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.websocket.*;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;

@Component
@ServerEndpoint("/ws/privateChat/{token}") // 连接路径 -- ws://localhost:8080/ws/privateChat/${token}
public class WebSocketServer_privateChat {
    private static final Logger LOG = LoggerFactory.getLogger(WebSocketServer_privateChat.class);
    
    // 存储所有连接
    private static final ConcurrentHashMap<String, Session> connections = new ConcurrentHashMap<>();
    
    private String token = "";
    private Session session;
    
    /**
     * 连接建立成功调用
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("token") String token) {
        this.session = session;
        this.token = token;
        connections.put(token, session);
        LOG.info("新连接: token={}, sessionId={}, 当前服务器已连接客服端数量={}",
                token, session.getId(), connections.size());
    }

    
    /**
     * 收到客户端消息
     */
    @OnMessage
    public void onMessage(String message, Session session) {

        try {
            // 前端js对象格式
//              const newMessage = {
//                    id: null,
//                    conversationId: conversation_Store.conversationInfo.id,
//                    senderId: sender_id,
//                    receiverId: talkerId.value,
//                    revoked: false,
//                    content: inputMessage.value.trim(),
//                    messageType: 1,
//                    status: 1,
//                    createTime: new Date().toLocaleString('zh-CN').replace(/\//g, '-'),
//                }
            JsonNode node = new ObjectMapper().readTree(message);
            String talkerId = node.get("receiverId").asText();
            String conversationId = node.get("conversationId").asText();

            if(talkerId.isEmpty()){
                LOG.error("接收者信息为空，会话id：{}", conversationId);
                return;
            }
            LOG.info("收到消息: token={}, message={}", token, message);
            sendToUser(talkerId, message); // 转发该消息给对应的用户

        } catch (Exception e) {
            LOG.error("解析消息失败: token={}, message={}", token, message, e);
        }
    }


    /**
     * 连接关闭
     */
    @OnClose
    public void onClose(Session session) {
        if (this.token != null && !this.token.isEmpty()) {
            connections.remove(this.token);
            LOG.info("连接关闭: token={}, sessionId={}, 当前连接数={}",
                    token, session.getId(), connections.size());
        }
    }


    /**
     * 发生错误
     */
    @OnError
    public void onError(Session session, Throwable error) {
        connections.remove(token);
        if (error instanceof java.io.IOException && 
            error.getCause() instanceof java.nio.channels.ClosedChannelException) {
            LOG.debug("WebSocket连接关闭异常（可能在应用关闭过程中）: token={}", token);
        } else {
            LOG.error("WebSocket错误: token={}", token, error);
        }
    }


    /**
     * 群发消息
     */
    public void broadcastMessage(String message) {
        for (Session session : connections.values()) {
            try {
                if (session.isOpen()) {
                    session.getBasicRemote().sendText(message);
                    LOG.info("服务器转发消息（群发）成功: 该消息来自会话token={}", token);
                }
            } catch (IOException e) {
                LOG.error("推送消息失败", e);
            }
        }
    }

    
    /**
     * 向指定用户发送消息
     */
    public void sendToUser(String token, String message) {
        Session session = connections.get(token);
        if (session != null && session.isOpen()) {
            try {
                session.getBasicRemote().sendText(message);
                LOG.info("向用户推送消息成功: 对方会话token={}", token);
            } catch (IOException e) {
                LOG.error("向用户推送消息失败: 对方会话token={}", token, e);
            }
        }
    }


    /**
     * 让所有会话都下线
     */
    public void offlineAll() {
        for (Session session : connections.values()) {
            try {
                if (session.isOpen()) {
                    session.close();
                    LOG.info("下线成功: sessionId={}", session.getId());
                }
            } catch (IOException e) {
                // 在应用关闭时，会话可能已经被关闭，这是正常现象
                LOG.debug("会话关闭失败（可能在应用关闭过程中）: sessionId={}", session != null ? session.getId() : "unknown", e);
            } catch (Exception e) {
                // 捕获其他可能的异常，避免影响应用关闭流程
                LOG.debug("会话关闭异常: sessionId={}", session != null ? session.getId() : "unknown", e);
            }
        }
        // 清空连接映射表
        connections.clear();
    }

    /**
     * 指定会话下线
     */
    public void offline(String token) {
        Session session = connections.get(token);
        if (session != null && session.isOpen()) {
            try {
                session.close();
                LOG.info("下线成功: sessionId={}", session.getId());
            } catch (IOException e) {
                // 在应用关闭时，会话可能已经被关闭，这是正常现象
                LOG.debug("会话关闭失败（可能在应用关闭过程中）: sessionId={}", session.getId(), e);
            } catch (Exception e) {
                // 捕获其他可能的异常，避免影响应用关闭流程
                LOG.debug("会话关闭异常: sessionId={}", session.getId(), e);
            }
        }
    }


    // 判断用户是否在线
    public boolean isUserOnline(String userId) {
        return connections.containsKey(userId) && connections.get(userId).isOpen();
    }

//    @PreDestroy
//    public void destroy() {
//        offlineAll();
//    }

}